<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
			<div>
				<input type="text" v-model="name" placeholder="姓名">
				<input type="text" v-model="age" placeholder="年龄">
				<input type="text" v-model="email" placeholder="邮箱">
				<input type="text" v-model="tel" placeholder="电话号码">
			</div>
			<div>
				<p>姓名：{{ name }}</p>
				<p>年龄：{{ age }}</p>
				<p>邮箱：{{ email }}</p>
				<p>电话：{{ tel }}</p>
			</div>
		</div>
		<script>
			class MVVM {
				constructor(el, data) {
					this.el = document.querySelector(el);
					this._data = data;
					this.domPool = {};
					this.init();
				}
				
				init() {
					this.initData();
					this.initDom();
				}
				
				initDom() {
					this.bindDom(this.el);
					this.bindInput(this.el);
				}
				
				initData() {
					const _this = this;
					this.data = {};
					for (let key in this._data) {
						Object.defineProperty(this.data, key, {
							get() {
								return _this._data[key];
							},
							set(newValue) {
								const oldValue = _this._data[key] || undefined;
								_this._data[key] = newValue;
								_this.replaceValue(_this.domPool[key], oldValue, newValue);
							}
						})
					}
				}
				
				bindDom(el) {
					const childNodes = el.childNodes;
					childNodes.forEach(item => {
						if (item.nodeType === 3) {
							const _value = item.nodeValue;
							if (_value.trim().length) {
								let exp = /\{\{(.+?)\}\}/;
								let isValid = exp.test(_value);
								if (isValid) {
									const [initValue, keyTrim] = _value.match(exp);
									const _key = keyTrim.trim();
									this.domPool[_key] = item.parentNode;
									this.replaceValue(item.parentNode, initValue, this.data[_key] || undefined);
								}
							}
						}
						item.childNodes && this.bindDom(item);
					});
				}
				
				bindInput(el) {
					const _allInputs = el.querySelectorAll("input");
					_allInputs.forEach(input => {
						const _vModel = input.getAttribute("v-model");
						if (_vModel) {
							input.addEventListener("input", this.handleInput.bind(this, _vModel, input), false);
						}
					})
				}
				
				handleInput(key, input) {
					const _value = input.value;
					this.data[key] = _value;
				}
				
				replaceValue(el, oldValue, newValue) {
					console.log(oldValue, newValue);
					el.innerHTML = el.innerHTML.replace(oldValue, newValue || undefined); 
				}
			}
			
			const app = new MVVM("#app", {
				name: "",
				age: "",
				email: "",
				tel: ""
			});
		</script>
	</body>
</html>